2019 下半年 Flutter 实现的性能优化 | 英雄榜
作者 / Yuqian Li & Shams Zakhour
高性能是 Flutter 的关键特性之一。我们希望通过本文着重分享在 2019 年下半年由整个 Flutter 社群实现的性能优化。(虽然 2020 年已经过去大半,但我们认为感谢开发者们做出的贡献虽晚不迟!)
当然,如果您在 2020 年帮助 Flutter 提升性能,您也将出现在未来的英雄榜中。我们希望通过分享这些成就,可以激励更多的开发者贡献能量!
我们尤其鼓励编写性能测试来量化性能上的提升,并防止该性能在未来出现倒退。因此,我们在含有量化结果的性能优化的详细说明中,会特别列出每个做出贡献的开发者。
以下是 2019 年下半年的 Flutter 性能汇总和量化结果分享,您可以在后文中阅读性能提升详细内容和贡献来源。
2019 年第 4 季度 (10 月 - 12 月)
快速滚动浏览大型图像时,内存占用减少 70%
简单 iOS 动画的 CPU/GPU 占用降低 40% 41% 的光标性能加速 通过修复光栅缓存节流,将列表滚动速度提高 10% 缓存性能数据使得仪表板加载速度提高 37 倍 构建 APK 的速度提高至 2.3 倍 Flutter 引擎提交时记录的性能指标增加 103 个 应用大小缩减 20% Dart FFI 性能提升了 108 倍 紧凑代码的性能提升 10% – 15% 通过新的增量序列化器将 flutter 测试速度提高了 2.2 倍 通过向 Dart VM JIT 提供内联提示将内核二进制序列化速度提高 10% 异步繁重代码的性能提升了 30%
其他改进
修复了在 iOS 上使用 PlatformView 时的内存泄漏问题 修复了在 iOS 上播放动画时的内存泄漏问题 修复了许多其它的 iOS 内存泄漏 已开始改造 flutter.dev 上的性能 (Performance) 页面并添加了有关衡量应用大小的操作说明 更正了第一帧等待逻辑和衡量 DevTools 添加了完整时间线模式,并支持异步和记录的追踪 IntelliJ 插件修复了 120FPS 支持 许多时间线追踪改进
2019 年第 3 季度 (7 月 - 9 月)
已量化的改进
矩形和点变换速度提升了 1.5–5 倍 iPhone X/Xs 滚动时丢失的帧数减少 N/2–1 通过并行初始化将引擎启动和关闭时间缩短 15% 着色器预热的启动速度加快 14.57 毫秒,内存使用量减少 8MB 代码大小缩减了 1.02%-8.04% Flutter 在 Fuchsia 上的 FPS 提高多达 2 倍;改进了帧时间安排
iOS 上 BackdropFilter 的速度提高 3 倍
DevTools 支持各种显示刷新速率 (例如 60 FPS、120 FPS 等) 目前 VSCode 插件对项目的扫描是异步扫描,这应该会提升扩展程序激活速度并降低触发 VS Code "扩展导致高 CPU" 警告的几率 iPhone Xs 已被添加至 Flutter 设备实验室进行基准测试
详细说明
PR 14265: 清理 IO 线程 GrContext https://github.com/flutter/engine/pull/14265 PR 46184: 针对快速滚动大型图像的内存测试 https://github.com/flutter/flutter/pull/46184 仪表板: fast_scroll_large_images__memory 中位数差值减少了 70% (从 400MB 减少到 120MB) https://flutter-dashboard.appspot.com/benchmarks.html Issue 19558: 需要清理 IO 线程 GrContext 内存 https://github.com/flutter/flutter/issues/19558
贡献者: liyuqian、dnfield、chinmaygarde
https://github.com/liyuqian
https://github.com/dnfield
https://github.com/chinmaygarde
PR 14104: 重新设计更简单的条件离屏渲染以实现屏幕读取支持 https://github.com/flutter/engine/pull/14104 PR 13976: 根据需求动态确定是否使用离屏表面 https://github.com/flutter/engine/pull/13976 PR 31865: iPhone 6 上的简单动画大量消耗 (约 20%) CPU/GPU/电量 https://github.com/flutter/flutter/issues/31865 simple_animation_perf_iphonexs 的 cpu_percentage 和 gpu_percentage 减少了 40% (从 23%-CPU-14%-GPU 减少到 13%-CPU-8.5%-GPU) https://github.com/flutter/flutter/issues/31865#issuecomment-566268237
https://github.com/flar http://github.com/liyuqian https://github.com/hixie http://github.com/chinmaygarde
PR 46720: 传递 _caretPrototype 以防止缓存丢失 https://github.com/flutter/flutter/pull/46720 PR 46720: 第 90 百分位帧的构建时间缩短了 41% (从 6.709 毫秒缩短到 4.756 毫秒) https://github.com/flutter/flutter/pull/46720 [已修复] Issue 24522: 光标性能低下,每帧的 GPU 时间过长 https://github.com/flutter/flutter/issues/24522
贡献者: garyqian、liyuqian、justinmc
https://github.com/garyqian http://github.com/liyuqian https://github.com/justinmc
PR 31865: iPhone 6 上的简单动画大量消耗 (约 20%) CPU/GPU/电量 https://github.com/flutter/flutter/issues/31865 PR 13710: 修复图片光栅缓存节流 https://github.com/flutter/engine/pull/13710 PR 45050: 为照片光栅缓存添加 perf 测试 https://github.com/flutter/flutter/pull/45050 利用 PR 13710 (修复图片光栅缓存节流) 修复了关键问题 43083: 列表滚动不畅 https://github.com/flutter/flutter/pull/45050
贡献者: liyuqian、chinmaygarde、flar、cyanglaz、zsunkun
http://github.com/liyuqian http://github.com/chinmaygarde https://github.com/flar https://github.com/cyanglaz https://github.com/zsunkun
PR 494: 缓存 get-benchmark https://github.com/flutter/cocoon/pull/494 PR 484: /api/public/get-status 提供缓存响应 https://github.com/flutter/cocoon/pull/484 基准加载速度提高至 37 倍 (从 37 秒缩短至 1 秒) https://github.com/flutter/cocoon/pull/494#issue-333227543
贡献者: caseyhillers、tvolkert、digiter、jonahwilliams
https://github.com/caseyhillers https://github.com/tvolkert https://github.com/digiter https://github.com/jonahwilliams
构建 APK 的速度提高至 2.3 倍
PR 44534: 通过并发运行 gen_snapshot 提高构建 APK 的性能 (大约 50%) https://github.com/flutter/flutter/pull/44534 针对目标平台 android-arm、android-arm64 和 android-x64,将 APK 的发布版本构建速度提高至 2.3 倍 (从 140 秒缩短至 60 秒) https://github.com/flutter/flutter/pull/44534#issue-339112036
贡献者: jonahwilliams、blasten、zanderso、xster
https://github.com/jonahwilliams https://github.com/blasten https://github.com/zanderso https://github.com/xster
PR 14556: 运行和收集指标 https://github.com/flutter/engine/pull/14556 相关 issue: PR 37434: 集中性能指标、提供通用提醒,并改进性能仪表板 https://github.com/flutter/flutter/issues/37434
贡献者: liyuqian、digiter、keyonghan、godofredoc、cbracken
http://github.com/liyuqian https://github.com/digiter https://github.com/keyonghan https://github.com/godofredoc https://github.com/cbracken
应用大小缩减 20%
3% 来自将 PC 偏移 (offset) 从 StackMaps 中移出 https://github.com/dart-lang/sdk/commit/a2bb7301c5795e6b28089a8dc96e6ab5ca798e22 2.58% 来自进一步压缩之前在 StackMaps 中的信息 https://github.com/dart-lang/sdk/commit/d77f4913a18ecce8c4be95cbaa4299ff1521dc10 1% 来自尽可能规范化 CompressedStackMaps 负载 (如可能) https://github.com/dart-lang/sdk/commit/dc808f3fcbf7e6de7e2b25441ff7ed891362e70a 2% 来自在裸机模式下完全启用指令去重 https://github.com/dart-lang/sdk/commit/e2faac751e1ef3707730e6e48f4d8f22ecbf35c3 0.3% 来自不为需要参数描述符的函数生成单态序言 https://github.com/dart-lang/sdk/commit/f6477854cdb0da052be3423a24961feaf5a0d845 1% 来自舍弃冗余的 null 初始化存储 https://github.com/dart-lang/sdk/commit/46cef9bfddf3cfc05618448d228f0e3377058baf 6% 来自减少指令对齐并移除一些调试陷阱指令 https://github.com/dart-lang/sdk/commit/8e7ffafbafc8203361111ddcafe0e0fcc372edf8 1.2% 来自在调用存根期间而非每个函数序言中调整 CSP https://github.com/dart-lang/sdk/commit/c873220e43af1a1f4675df4108e575465e598578 1% 来自 ARM64: 屏蔽 R22 以保留 NullObject() https://github.com/dart-lang/sdk/commit/f8d42542ddd40c06bb71d6fb85d78ed4bbffa785 2.5% 来自全程序常量传播 https://github.com/dart-lang/sdk/commit/f56b0f690789b6f0e2e5bc1340abf4eba414b7a0 0.77% 来自消除死代码 https://github.com/dart-lang/sdk/commit/b69596bb1ba81874e4b9d7a577071c67c357ec39
贡献者: mraleph、alexmarkov、rmacnak-google、mkustermann、sstrickl、aartbik
https://github.com/mraleph https://github.com/alexmarkov https://github.com/rmacnak-google https://github.com/mkustermann https://github.com/sstrickl https://github.com/aartbik
Dart FFI 性能提升了 108 倍
Gerrit 120661: 优化静态已知类型的指针操作 https://dart-review.googlesource.com/c/sdk/+/120661 Gerrit 119645: 索引读取和存储的指针优化 https://dart-review.googlesource.com/c/sdk/+/119645 Gerrit 121580: 允许在 AoT 中内嵌强制优化的函数 https://dart-review.googlesource.com/c/sdk/+/121580
贡献者: dcharkes、mkustermann、sjindel、alexmarkov
https://github.com/dcharkes https://github.com/mkustermann https://github.com/sjindel https://github.com/alexmarkov
Gerrit 117200: 循环分析和 BCE 改进 https://dart-review.googlesource.com/c/sdk/+/117200 golem armv7 的性能提高了 10–15%,以及 TypedData Bench: Gerrit 117200: 循环分析和 BCE 改进 https://dart-review.googlesource.com/c/sdk/+/117200
贡献者: aartbik、mkustermann、mraleph
https://github.com/aartbik https://github.com/mkustermann https://github.com/mraleph
通过新的增量序列化器将 flutter 测试速度提高了 2.2 倍
Gerrit 121121: 默认启用增量序列化器 https://dart-review.googlesource.com/c/sdk/+/121121 "flutter test" 速度提高了 2.2 倍 (时间从 3:38 缩短至 1:39)
贡献者: jensjoha、alexmarkov
https://github.com/jensjoha https://github.com/alexmarkov
Gerrit 119540: 向内核序列化中的某些方法添加 VM 友好内联指令 https://dart-review.googlesource.com/c/sdk/+/119540
贡献者: jensjoha、johnniwinther
https://github.com/jensjoha https://github.com/johnniwinther
添加非紧急异步堆栈帧收集器 https://dart-review.googlesource.com/c/sdk/+/122644
贡献者: cskau-g、mkustermann、mraleph
https://github.com/cskau-g https://github.com/mkustermann https://github.com/mraleph
2019 年第 4 季度其他改进
修复了在 iOS 上使用 PlatformView 时的内存泄漏问题
修复使用 PlatformView [IOS] 时的内存泄漏 https://github.com/flutter/engine/pull/7919 使用 PlatformView [IOS] 时的内存泄漏 https://github.com/flutter/flutter/issues/24714
修复了在 iOS 上播放动画时的内存泄漏问题
Gerrit 260538: 不为创建无法缓存纹理的生成器分配无效消息 https://skia-review.googlesource.com/c/skia/+/260538 在 iOS 上播放动画时的内存泄漏 https://github.com/flutter/flutter/issues/47108
https://github.com/flutter/engine/pull/14275
https://github.com/flutter/engine/pull/14326
https://github.com/flutter/flutter/issues/35243
已开始改造 flutter.dev 上的性能 (Performance) 页面并添加了有关衡量应用大小的操作说明
PR 3159: 性能 https://github.com/flutter/website/pull/3159/
PR 37192: 重新 "修复追踪和驱动程序中的第一帧逻辑 (#35297)" https://github.com/flutter/flutter/pull/37192 修复了 issue 47108: 在 iOS 上播放动画时的内存泄漏 https://github.com/flutter/flutter/issues/47108
DevTools 添加了完整时间线模式,并支持异步和记录的追踪
PR 1241: 添加完整时间线视图 https://github.com/flutter/devtools/pull/1241
IntelliJ 插件修复了 120FPS 支持
PR 4289: 移除硬编码的刷新速率以进行 fps 计算 https://github.com/flutter/flutter-intellij/pull/4289
更多时间线追踪改进
Gerrit 127920: [时间线] 添加对 android 平台追踪中时间线异步事件的支持 https://dart-review.googlesource.com/c/sdk/+/127920 Gerrit 128200: [时间线] 支持适用于 systrace 的 vm 事件 https://dart-review.googlesource.com/c/sdk/+/128200 Gerrit 127921: 使用 systrace 记录时间线事件时支持更多同步事件 https://dart-review.googlesource.com/c/sdk/+/127921 PR 14323: 修复使用 systrace 记录事件时缺少 API 流的问题 https://github.com/flutter/engine/pull/14323 PR 14521: 可以在发布版本模式下启用支持时间线 https://github.com/flutter/engine/pull/14521 PR 14319: 修复 flutter 引擎启动时缺少时间线事件的问题 https://github.com/flutter/engine/pull/14319 PR 47742: 修复时间线摘要时长事件 https://github.com/flutter/flutter/pull/47742 Gerrit 131360: 支持时间线转化为 iOS 平台追踪 https://dart-review.googlesource.com/c/sdk/+/131360 PR 16520: 支持无限追踪缓冲 https://github.com/flutter/engine/pull/16520 PR 47419: 支持无限时间线记录器 https://github.com/flutter/flutter/pull/47419
PR 37275: 优化 matrix_utils 中的 transformRect 和 transformPoint 方法 https://github.com/flutter/flutter/pull/37275 MatrixUtils_affine_transformRect_iteration 速度提升至 5.3 倍 (从 2,300 毫秒缩短至 430 毫秒) MatrixUtils_affine_transformPoint_iteration 速度提升至 1.5 倍 (从 466 毫秒缩短至 320 毫秒)
贡献者: flar、yjbanov、dnfield
https://github.com/flar https://github.com/yjbanov https://github.com/dnfield
https://github.com/flutter/engine/pull/12385
PR 12385: 再处理 "iOS 不规则输入事件交付" https://github.com/flutter/engine/pull/12385 将滚动 N 个帧时丢失帧的数量 (最糟糕情况) 从 N/2 减少至 1。实机测试中,在修复之前平均丢失的帧数量为 N/10 个。 修复了以下得票数最多的 issue 之一: Issue 31086: 由于不规则输入事件交付,iPhone X、Xs 设备上的滚动性能严重下降 https://github.com/flutter/flutter/issues/31086
贡献者: liyuqian、chinmaygarde、gaaclarke
http://github.com/liyuqian
http://github.com/chinmaygarde
https://github.com/gaaclarke
通过并行初始化将引擎启动和关闭时间缩短 15%
PR 10182: 通过允许对初始化进行并行处理加快了 flutter 启动速度
https://github.com/flutter/engine/pull/10182
BM_ShellInitializationAndShutdown 的速度提升至 1.16 倍 (从 3,829,377 纳秒缩短至 3,286,713 纳秒)
https://github.com/flutter/engine/pull/10182#issuecomment-531953100
贡献者: gaaclarke、chinmaygarde、liyuqian
https://github.com/gaaclarke http://github.com/chinmaygarde http://github.com/liyuqian
PR 36482: 通过仅在 100x100 表面上绘制加快了着色器预热速度 https://github.com/flutter/flutter/pull/36482 启动时读取/转换像素的时间节省了 14.57 毫秒 (从 18.848 毫秒缩短至 4.279 毫秒) https://github.com/flutter/flutter/pull/36482#issue-299068276 启动内存中位数节省了 8MB (从 39,220KB 减少到 31,184KB) https://github.com/flutter/flutter/pull/36482#issuecomment-531067365 结束内存中位数节省了 4MB (从 45,034KB 减少到 40,980KB) https://github.com/flutter/flutter/pull/36482#issuecomment-531067365
贡献者: gaaclarke、liyuqian、dnfield
https://github.com/gaaclarke http://github.com/liyuqian https://github.com/dnfield
https://dart-review.googlesource.com/c/sdk/+/118280
https://dart-review.googlesource.com/c/sdk/+/112758
https://dart-review.googlesource.com/c/sdk/+/118181
armv8 animation_bench_instructions_size 减小 8.04% (从 5.57MB 缩减至 5.13MB) armv7 flutter_gallery_readonlydata_size 减小 2.7% (从 2.10MB 减少至 2.05MB) armv7 layout_bench_instructions_size 减小 1.22% (从 2.10MB 减少至 2.05MB)
贡献者: johnniwinther、aartbik、rmacnak-google、jensjoha、alexmarkov、mkustermann
https://github.com/johnniwinther https://github.com/aartbik https://github.com/rmacnak-google https://github.com/jensjoha https://github.com/alexmarkov https://github.com/mkustermann
Flutter 在 Fuchsia 上的 FPS 提高多达 2 倍;改进了帧时间安排
https://fuchsia-review.googlesource.com/c/topaz/+/280230
https://fuchsia-review.googlesource.com/c/topaz/+/286735
https://fuchsia-review.googlesource.com/c/topaz/+/300135
https://fuchsia-review.googlesource.com/c/topaz/+/306773
https://fuchsia-review.googlesource.com/c/topaz/+/306772
https://fuchsia-review.googlesource.com/c/topaz/+/307953
贡献者: dreveman、amott、rosswang、mikejurka
https://github.com/dreveman https://github.com/amott https://github.com/rosswang https://github.com/mikejurka
https://skia-review.googlesource.com/c/skia/+/237904
https://skia-review.googlesource.com/c/skia/+/234413
https://github.com/flutter/flutter/pull/38814
GM_savelayer_with_backdrop 的速度加快了 3 倍 (从 110 毫秒缩短至 34 毫秒)
https://perf.skia.org/e/?begin=1567010155&end=1567104574&queries=name%3DGM_savelayer_with_backdrop%26os%3DiOS
修复了回退 https://github.com/flutter/flutter/issues/36064
贡献者: lhkbob、liyuqian、flar
https://github.com/lhkbob http://github.com/liyuqian https://github.com/flar
之所以能够实现这些大幅度的改进 (例如提升至 3 倍之多),除去 2019 年的努力外,老版本不尽如人意的表现可能也有所 "贡献"。我们也在此分享一些同样重大的性能回退问题的修复结果。我们对这些努力深表感激,如果没有这些工作,我们会继续面临性能不佳乃至回退的问题。当然,我们也不希望大幅度的改进令较小的提升相形见绌: 有时候性能的小幅度提升仅仅只是因为起点太高,这本是好事。
DevTools 支持各种显示刷新速率 (例如 60 FPS、120 FPS 等) https://github.com/flutter/devtools/blob/master/packages/devtools/CHANGELOG.md#018---2019-10-01 目前 VSCode 插件对项目的扫描是异步扫描,这应该会提升扩展程序激活速度并降低触发 VS Code "扩展导致高 CPU" 警告的几率。(#1840/#2003/#1961) https://github.com/Dart-Code/Dart-Code/issues/1840 https://github.com/Dart-Code/Dart-Code/issues/2003 https://github.com/Dart-Code/Dart-Code/issues/1961 iPhone Xs 已被添加至 Flutter 设备实验室进行基准测试 https://github.com/flutter/flutter/issues/34590
结论
△ 53% 的受访者对 Flutter 表示非常满意
得益于这些贡献,Flutter 移动端性能的满意度从 2019 年第三季度的 85% 上升到 2020 年的 92%。本文虽已尽力列出大家的贡献,但仍然可能遗漏 2019 年第 3 到第 4 季度的一些贡献。如果有任何遗漏的贡献,请随时告诉我们,我们会将其纳入下一次更新。
Flutter 2020 年第三季度调研已经开启,本次调研会重点涉及移动端和 Web 端的体验细节,以及询问您对一些动画效果的看法。扫描二维码进入调研,请注意本次调研将于 2020 年 8 月 27 日截止。
推荐阅读